package com.eryos.android.cigarettecounter.database;

import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.database.Cursor;
import android.util.Log;

/**
 * Project : CigaretteCounter Author : Olivier Combe URL : http://eryos.fr/CigaretteCounter/
 * 
 * Copyright(C)2011 - Olivier Combe
 * 
 * Licensed under the Apache License, Version 2.0(the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 * 
 * @version \$Revision.*\$
 * @author Olivier Combe
 */
public class CigaretteDatabase extends DBConnector {

    private static final String CSV_SEPARATOR = ";";

    private static CigaretteDatabase currentDB;

    private final WeeklyAdapterImpl weeklyAdapter;
    private final MonthlyAdapterImpl monthlyAdapter;
    private final DailyAdapterImpl dailyAdapter;

    /**
     * Create a new CigaretteDatabase Object link to the context in argument.
     * 
     * @param ctx
     *            Application context
     */
    protected CigaretteDatabase(final Context ctx) {
        super(ctx);
        weeklyAdapter = new WeeklyAdapterImpl(this);
        monthlyAdapter = new MonthlyAdapterImpl(this);
        dailyAdapter = new DailyAdapterImpl(this);
    }

    /**
     * @return the current Weekly adpater.
     */
    public WeeklyAdapterImpl getWeeklyAdapter() {
        return weeklyAdapter;
    }

    /**
     * @return the current Montlhy adpater.
     */
    public ExtendedPeriodicAdapterInterface getMonthlyAdapter() {
        return monthlyAdapter;
    }

    /**
     * @return the current Daily adpater.
     */
    public DailyAdapterImpl getDailyAdapter() {
        return dailyAdapter;
    }

    /**
     * @param ctx
     *            application context
     * @return an instance of the database.
     */
    public static CigaretteDatabase getInstance(final Context ctx) {
        if (currentDB == null) {
            currentDB = new CigaretteDatabase(ctx);
        }

        return currentDB;
    }

    /**
     * @return the dtabase name
     */
    public String getDatabaseName() {
        return DBConnector.DATABASE_TABLE;
    }

    /** ************************************************************************** **/

    /**
     * Insert 'now' in database.
     * 
     * @param reason
     *            : reason / label / description of the moment
     * @param price
     *            : unit price of cigarette
     */
    public void insertCurrentTimestamp(final String reason, final float price) {
        Log.d(getClass().getSimpleName(), "Insert Current TS");
        long epoch = System.currentTimeMillis() / 1000;

        insertTimestamp(price, epoch, reason);
    }

    /**
     * Insert a specific timestamp in DB.
     * 
     * @param price
     *            : unit price of cigarette
     * @param timestamp
     *            : time to insert in DB
     * @param reason
     *            : reason / label / description of the moment
     */
    public void insertTimestamp(final float price, final long timestamp, final String reason) {
        db.execSQL("INSERT INTO " + DBConnector.DATABASE_TABLE
                + "(smoke_time, smoke_reason, smoke_valid)VALUES(datetime(" + timestamp
                + ", 'unixepoch', 'localtime'), '" + reason + "', " + price + ");");
    }

    /**
     * Delete all data from database.
     */
    public void deleteAll() {
        Log.d(getClass().getSimpleName(), "Delete All");
        db.execSQL("DELETE FROM " + DBConnector.DATABASE_TABLE + ";");
    }

    /** ************************************************************************** **/

    /**
     * Export data to String version(list).
     * 
     * @return list of data to write
     */
    public List<String> exportData() {
        Log.d(getClass().getSimpleName(), "Export data");

        ArrayList<String> data = new ArrayList<String>();

        data.add("Smoke Time" + CSV_SEPARATOR + "Smoke Reason" + CSV_SEPARATOR + "Smoke Price");

        try {
            String sqlQuery = "SELECT strftime('%Y-%m-%d %H:%M:%S', " + DBConnector.TIME_COLUMN + "), "
                    + DBConnector.REASON_COLUMN + ", " + DBConnector.PRICE_COLUMN + " " + "FROM  " + getDatabaseName()
                    + "; ";

            Cursor mCursor = db.rawQuery(sqlQuery, null);

            if (mCursor != null) {
                mCursor.moveToFirst();

                while (mCursor != null && !mCursor.isAfterLast()) {
                    String line = mCursor.getString(0) + CSV_SEPARATOR + mCursor.getString(1) + CSV_SEPARATOR
                            + mCursor.getFloat(2);
                    data.add(line);
                    mCursor.moveToNext();
                }
            }
            Log.d(getClass().getSimpleName(), data.size() + "line(s)exported");

        } catch (Exception e) {
            Log.e(this.getClass().getSimpleName(), "Export Data", e);
        }

        return data;
    }

    /**
     * Method used to store in DB all data contained in the ArrayList in param.
     * 
     * @param data
     *            : List of data in CSV format
     * @return number of lines inserted
     */
    public int importData(final List<String> data) {
        Log.d(this.getClass().getSimpleName(), "Import Data");
        int nbImport = 0;
        for (String line : data) {

            if (!line.startsWith("Smoke")) {
                String[] tmpValues = line.split(CSV_SEPARATOR);

                String sqlQuery = "INSERT INTO " + getDatabaseName() + "(" + DBConnector.ROWID_COLUMN + ", "
                        + DBConnector.TIME_COLUMN + ", " + DBConnector.REASON_COLUMN + ", " + DBConnector.PRICE_COLUMN
                        + ")VALUES(null, '" + tmpValues[0] + "', '" + tmpValues[1] + "', '" + tmpValues[2] + "');";
                db.execSQL(sqlQuery);
                nbImport++;
            }
        }

        Log.d(getClass().getSimpleName(), nbImport + "line(s)imported");
        return nbImport;
    }

}
